package com.github.data_manage.config

import cn.dev33.satoken.exception.NotLoginException
import cn.dev33.satoken.exception.NotPermissionException
import com.github.data_manage.common.CommonResult
import jakarta.validation.ConstraintViolationException
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import org.springframework.beans.factory.annotation.Value
import org.springframework.http.HttpStatus
import org.springframework.web.bind.annotation.ExceptionHandler
import org.springframework.web.bind.annotation.ResponseStatus
import org.springframework.web.bind.annotation.RestControllerAdvice
import org.springframework.web.context.request.RequestContextHolder
import org.springframework.web.context.request.ServletRequestAttributes

/**
 * @author 18066
 * @since 2020/11/11
 */
@RestControllerAdvice
class SystemExceptionHandler {

    companion object {
        val log: Logger = LoggerFactory.getLogger(SystemExceptionHandler::class.java)
    }

    @Value($$"${system.error-log-enabled:true}")
    open var errorLogEnabled: Boolean = true

    @ExceptionHandler(Exception::class)
    @ResponseStatus(HttpStatus.OK)
    fun handle(exception: Exception): CommonResult<Boolean?> {
        if (exception is ConstraintViolationException) {
            val violations = exception.constraintViolations
            for (item in violations) {
                //打印验证不通过的信息
                if (errorLogEnabled) {
                    log.error("错误请求,路径为[{}]异常为", getCurrentRequestUri(), exception)
                }
                return CommonResult.failed(item.message)
            }
        }
        if (errorLogEnabled) {
            log.error("请求的路径[{}]发生错误", getCurrentRequestUri(), exception)
        }
        return CommonResult.failed("发生错误" + exception.message)
    }

    @ExceptionHandler(SystemException::class)
    @ResponseStatus(HttpStatus.OK)
    fun handleSystemException(exception: SystemException): CommonResult<Boolean?> {
        if (errorLogEnabled) {
            log.error("请求的路径[{}]发生错误", getCurrentRequestUri(), exception)
        }
        if (exception.code == FUND_NO_DATA_EXCEPTION) {
            return CommonResult.success(data = false, message = "基金无数据")
        }
        return CommonResult.failed(exception.message)
    }


    @ExceptionHandler(NotPermissionException::class)
    @ResponseStatus(HttpStatus.FORBIDDEN)
    fun handleNoPermissionException(exception: NotPermissionException): CommonResult<Boolean?> {
        return CommonResult(403, "请求错误,没有权限访问", null)
    }

    @ExceptionHandler(NotLoginException::class)
    @ResponseStatus(HttpStatus.UNAUTHORIZED)
    fun handleNotLoginException(exception: NotLoginException): CommonResult<Boolean?> {
        return CommonResult(401, "请求需要登录", null)
    }


    /**
     * 获取当前请求的uri路径
     *
     * @return 当前请求的uri路径
     */
    private fun getCurrentRequestUri(): String? {
        val request = (RequestContextHolder.currentRequestAttributes() as ServletRequestAttributes).request
        return request.requestURI
    }
}

const val NORMAL_EXCEPTION = 1;

const val FUND_NO_DATA_EXCEPTION = 2;

class SystemException(
    override val message: String,
    val code: Int = NORMAL_EXCEPTION
) : RuntimeException(message) {

}
